#include "stk_base.h"
#include "stk_const.h"
#include "stk_utility.h"
#include <string.h>


struct MsgFieldName
{
    uint32_t     nType;
    const char * szName;
};

MsgFieldName g_MsgFieldNameList[] =
{
    { STK_FD_NAME_UNKNOW,            "unkown"                  },
    { STK_FD_NAME_ACCEPT,            STK_COMM_ACCEPT           },
    { STK_FD_NAME_ACCEPT_ENCODING,   STK_COMM_ACCEPT_ENCODING  },
    { STK_FD_NAME_ACCEPT_LANGUAGE,   STK_COMM_ACCEPT_LANGUAGE  },
    { STK_FD_NAME_AUTHORIZATION,     STK_COMM_AUTHORIZATION    },
    { STK_FD_NAME_CSEQ,              STK_COMM_CSEQ             },

    { STK_FD_NAME_CONTENT_ENCODING,  STK_COMM_CONTENT_ENCODING },
    { STK_FD_NAME_CONTENT_LANGUAGE,  STK_COMM_CONTENT_LANGUAGE },
    { STK_FD_NAME_CONTENT_LENGTH,    STK_COMM_CONTENT_LENGTH   },
    { STK_FD_NAME_CONTENT_TYPE,      STK_COMM_CONTENT_TYPE     },
    { STK_FD_NAME_CONTENT_BASE,      STK_COMM_CONTENT_BASE     },

    { STK_FD_NAME_DATE,              STK_COMM_DATE             },
    { STK_FD_NAME_USER_AGENT,        STK_COMM_USER_AGENT       },
    { STK_FD_NAME_SERVER,            STK_COMM_SERVER           },
    { STK_FD_NAME_WWW_AUTHENTICATE,  STK_COMM_WWW_AUTHENTICATE },
    { STK_FD_NAME_HOST,              STK_HTTP_HOST             },

    { STK_FD_NAME_CONNECTION,        STK_HTTP_CONNECTION       },
    { STK_FD_NAME_LOCATION,          STK_HTTP_LOCATION         },
    { STK_FD_NAME_PUBLIC,            STK_COMM_PUBLIC           },
    { STK_FD_NAME_RANGE,             STK_COMM_RANGE            },
    { STK_FD_NAME_VARY,              STK_COMM_VARY             },

    { STK_FD_NAME_SESSION,           STK_RTSP_SESSION          },
    { STK_FD_NAME_TRANSPORT,         STK_RTSP_TRANSPORT        },
    { STK_FD_NAME_RTP_MESSAGE,       STK_RTSP_RTP_MESSAGE      },
    { STK_FD_NAME_SCALE,             STK_RTSP_SCALE            },
    { STK_FD_NAME_CACHE_CONTROL,     STK_COMM_CACHE_CONTROL    },
};

MsgParamList::MsgParamList()
{
}

MsgParamList::~MsgParamList()
{
    clear();
}

void MsgParamList::clear()
{
    while (!m_ParamList.eol(0))
    {
        MsgParam *pParam = (MsgParam *) m_ParamList.get(0);
        m_ParamList.remove(0);
        delete pParam;
    }
}

MsgParamList & MsgParamList::operator= (const MsgParamList &src)
{
    int pos = 0;

    while (!src.m_ParamList.eol(pos))
    {
        MsgParam *pParam;
        MsgParam *pParam2;

        pParam = (MsgParam *)src.m_ParamList.get(pos);
        pParam2 = new MsgParam(*pParam);

        if (NULL == pParam2)
        {
            this->clear();
            return *this;
        }

        m_ParamList.add(pParam2, -1);
        pos++;
    }

    return *this;
}

int32_t MsgParamList::to_str(string & strBuffer, bool bAllowValueNull)
{
    int pos = 0;

    while (!m_ParamList.eol(pos))
    {
        MsgParam *pParam = (MsgParam *) m_ParamList.get (pos);

        if (!bAllowValueNull)
        {
            if (pParam->m_name.empty() || pParam->m_value.empty())
            {
                pos++;
                continue;
            }
        }

        strBuffer += string(";") + pParam->m_name;

        if (!pParam->m_value.empty())
        {
            strBuffer += string("=") + pParam->m_value;
        }

        pos++;
    }

    return 0;
}

int32_t MsgParamList::parse_params(string szParams)
{
    string	strName = "";
    string	strValue = "";
    const char *tmp;

    const char *comma;
    const char *equal;

    /* find '=' wich is the separator for one param */
    /* find ';' wich is the separator for multiple params */

    tmp = szParams.c_str();
    equal = stk_next_separator (tmp + 1, '=', ';');
    comma = strchr(tmp + 1, ';');

    while (comma != NULL)
    {
        if (equal == NULL)
        {
            equal = comma;
            strValue = "";
        }
        else
        {
            if (comma - equal < 2)
            {
                return -1;
            }

            strValue.assign(equal + 1, comma - equal - 1);
            //stksip_uri_unescape (strValue);
        }

        if (equal - szParams.c_str() < 2)
        {
            return -1;
        }

        strName.assign(tmp + 1, equal - tmp - 1);
        //stksip_uri_unescape (strName);

        add(strName, strValue);

        tmp = comma;
        equal = stk_next_separator (tmp + 1, '=', ';');
        comma = strchr (tmp + 1, ';');
    }

    /* this is the last header (comma==NULL) */
    comma = tmp;
    equal = stk_next_separator (tmp + 1, '=', ';');

    if (equal == NULL)
    {
        equal = comma;            /* at the end */
        strValue = "";
    }
    else
    {
        strValue = equal + 1;
    }

    strName.assign(tmp + 1, equal - tmp - 1);
    //stksip_uri_unescape (strName);

    add(strName, strValue);

    return 0;
}

int32_t MsgParamList::add(const string & szName, const string & szValue)
{
    if (szName.empty())
    {
        return -1;
    }

    MsgParam* pParam = new MsgParam(szName.c_str(), szValue.c_str());

    if (pParam)
    {
        m_ParamList.add(pParam, -1);
        return -1;
    }

    return -1;
}

MsgParam *MsgParamList::get_byname(const char *strName) const
{
    if (!strName)
    {
        return NULL;
    }

    int pos = 0;

    while (!m_ParamList.eol(pos))
    {
        MsgParam *pParam = (MsgParam *) m_ParamList.get (pos);

        if (pParam->m_name == strName)
        {
            return pParam;
        }

        pos++;
    }

    return NULL;
}

const char* MsgField::GetTypeName()
{
    int nNum = sizeof(g_MsgFieldNameList) / sizeof(MsgFieldName);

    for (int i = 0 ; i < nNum; i++)
    {
        if (g_MsgFieldNameList[i].nType == GetType())
        {
            return g_MsgFieldNameList[i].szName;
        }
    }

    return g_MsgFieldNameList[0].szName;
}

/* 拷贝 */
MsgField &MsgField::operator= (const MsgField &src)
{
    m_uTypeID    = src.m_uTypeID;
    m_uSessionID = src.m_uSessionID;

    return *this;
}


MsgFieldList::MsgFieldList()
{
}

MsgFieldList::~MsgFieldList()
{
    clear();
}

void MsgFieldList::clear()
{
    while (!m_listField.eol(0))
    {
        MsgField *pField = (MsgField *)m_listField.get(0);
        m_listField.remove(0);
        delete pField;
    }
}

MsgField *MsgFieldList::get(int32_t pos)
{
    return (MsgField *)m_listField.get(pos);
}

int32_t MsgFieldList::push(MsgField *field)
{
    return m_listField.add(field, 0);
}

int32_t MsgFieldList::add(MsgField *field)
{
    return m_listField.add(field, -1);
}

int32_t MsgFieldList::remove(int32_t pos)
{
    MsgField *pField = m_listField.get(pos);

    int32_t ret = m_listField.remove(pos);

    if (pField)
    {
        delete pField;
    }

    return ret;
}
